import random
from BlockChain import Blockchain
from Wallet import Wallet

blockchain = Blockchain()


class Network(object):

    def __init__(self):
        self.peers = set()
        self.off_peers = []

    def create_genesis_block(self):  # TODO part 
        genesis_block = blockchain.create_genesis_block()
        return genesis_block

    def add_peer(self, host, port):  # TODO part 2
        peer = Peer()  # 创建一个新的节点对象
        peer.host = host  # 设置节点的主机地址
        peer.port = port  # 设置节点的端口号
        self.peers.add(peer)  # 将新节点添加到网络中

    def login(self, peer):  # TODO part 3
        if peer in self.peers:
            print(str(peer.peerName)+"已经登陆！")
        else:
            print("peer"+ str(peer.peerName)+"连接P2P网络成功")
            self.peers.append(peer)
            peer.online = True
            return str(self.peers)

    def logout(self, peer):  # TODO part 4
        if len(self.peers)<1:
            print("网络中没有任何节点！")
            return
        if not peer in self.peers:
            print("该节点不在网络中！")
        else:
            self.peers.remove(peer)
            self.off_peers.append(peer)
            peer.online = False
            print("注销成功！")
        return str(self.off_peers)
        

    def peer_online(self):  # TODO part 5
        peer_online = []
        for peer in Network.peers:
            peer_online.append(peer.peerName)
        print("当前网络中节点在线：" + str(peer_online))
        return peer_online
    def create_peer(self, peer):
        peer.pid = self.nop
        peer.wallet.generate_keys()
        self.peers.append(peer)

    def generate_random_peer(self, n):
        host = '127.0.0.1'
        for i in range(5):
            port = random.randint(5001, 9000)
            self.add_peer(host, port)
        return self.peers


class Peer:
    def __init__(self, name=None):  # 节点初始化函数
        self.online = False
        self.peerName = name
        self.chain = []
        self._is_wallet_generated = False
        self.generate_wallet()

    def generate_wallet(self):  # 用于节点生成钱包对象
        if not self._is_wallet_generated:
            self.wallet = Wallet()
            self._is_wallet_generated = True

    '''
    节点区块链同步函数。
    用于节点与网络之间的区块链进行数据同步。
    '''

    def sync_blockchain(self, blockchain):  # TODO part 6
        if len(self.chain) < blockchain.get_height():  # 检查本地区块链的长度是否小于接收到的区块链的长度
            chaindata = blockchain.get_chain()  # 如果是，获取接收到的区块链数据
            for block in chaindata:  # 遍历接收到的区块链中的每个区块
                self.chain.append(block)  # 将每个区块添加到本地区块链的末尾
        return self.chain  # 返回更新后的本地区块链


    def print_blockchain(self):  # 输出节点的区块链副本数据
        print("本节点区块链包含区块个数: %d" % len(self.chain))
        for block in self.chain:
            print("区块索引：%s" % block['index'])
            print("上个区块哈希：%s" % block['previous_hash'])
            print("区块交易信息：%s" % block['transactions'])
            print("本区块哈希：%s" % block['hash'])
            print("===========================================================================\n")

    '''
    节点版本的交易函数。
    用于节点之间发送交易数据。交易需要后续挖矿来确认从而产生新的区块。
    '''

    def send_transaction(self, sender, receiver, tx_data):  # TODO part 7
        if sender.online is False:
            print("发送方节点不在线！")
        else:
            sender = sender.wallet.address.encode()
            receiver = receiver.wallet.address.encode()
            blockchain.send_transaction(sender, receiver, tx_data)
            print("交易已发送！")
